package com.zdft.promotion.common.util.rpc;

import com.alibaba.fastjson.JSON;
import com.zdft.esb.bean.EsbResponse;
import com.zdft.esb.constant.EsbConstant;
import com.zdft.esb.enter.EsbClient;
import com.zdft.promotion.RpcServiceException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;

/**
 * PRC代理处理器
 */
public class RpcHandler implements InvocationHandler {
    private final Class<?> clazz;
    private final Logger   log;
    private final String   ip;
    private final int      port;

    RpcHandler(Class<?> clazz, String ip, int port) {
        this.clazz = clazz;
        log = LoggerFactory.getLogger(clazz);
        this.ip = ip;
        this.port = port;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /*RpcCall classAnn = clazz.getDeclaredAnnotation(RpcCall.class);
        if (null == classAnn) {
            throw new UnsupportedOperationException("Not registered on esb!class:" + clazz.getName());
        }*/

        RpcCall methodAnn = method.getDeclaredAnnotation(RpcCall.class);
        if (null == methodAnn) {
            throw new UnsupportedOperationException(
                    "Not registered on esb!class:" + clazz.getName() + "." + method.getName());
        }

        //log.debug("Start invoking method:{}...", method);
        String argStr = JSON.toJSONString(args);
        //log.debug("Parameters:{}", argStr);

        Type[] argTypes = method.getGenericParameterTypes();
        Parameter[] parameters = method.getParameters();

        EsbClient client = new EsbClient(ip, port);
        client.requestSyn(true);
        client.bindService(methodAnn.beanName(), StringUtils.isEmpty(methodAnn.mothodName()) ? method.getName() : methodAnn.mothodName());
        if (null != args && args.length > 0) {
            for (int i = 0; i < args.length; i++) {
            	if(parameters[i].getAnnotation(RpcCallParam.class) != null){
            		client.addParam(parameters[i].getAnnotation(RpcCallParam.class).value(), args[i]);
            	} else {
            		client.addParam(argTypes[i].getTypeName(), args[i]);
            	}
            }
        }
        EsbResponse response = client.send();
        String resCode = response.getResCode();
        if (EsbConstant.ESB_SERVICE_STATUS_SUCCESS.equals(resCode)) {
            //log.debug("Return:{}.", JSON.toJSONString(response));
            return JSON.parseObject(response.getResBody4Cust(), method.getGenericReturnType());
        }
        //log.debug("Parameters:{},\nReturn:{}", argStr, JSON.toJSONString(response));
        throw new RpcServiceException(resCode, response.getResBody4Cust());
    }
}